
/**
\file
Definition of the base sun::game_state class.
\author Sean Tromans
*/

#include <sun_pre_compiled.hpp>
#include <sun/game_state/game_state.hpp>

#if !defined(SUN_DISABLE_LUA)
#include <sun/lua/lua.hpp>
#endif

namespace sun
{

	namespace detail
	{
#if !defined(SUN_DISABLE_LUA)
		/**
		Wrapper class to allow lua to inherit from a game_state.
		\author Sean Tromans
		*/
		class game_state_wrapper :	public game_state,
									public luabind::wrap_base
		{
			//
			//	Public Member Functions
			//
			public:

				/**
				Luabind seems to require this to have a constructor if it's a class. It works fine without one if it's a struct though/
				\author Sean Tromans
				*/
				game_state_wrapper( )
				{
				}

				/**
				Updates the game state by \c delta_time.
				@param delta_time The time passed since the last update.
				@return The state which should replace this state next update.
				\author Sean Tromans
				*/
				virtual state_ptr step( time const & delta_time )
				{
					return call< state_ptr >( "step", boost::ref( delta_time ) );
				}

				/**
				Called once before each frame is drawn. All required viewports should be pushed onto the viewport queue.
				@param step_fraction How far between logic updates this frame is.
				@param stack The stack of viewports being drawn so far this frame.
				\author Sean Tromans
				*/
				virtual void pre_draw( float step_fraction, rainbow::viewport_stack & stack )
				{
					call< void >( "pre_draw", step_fraction, boost::ref( stack ) );
				}

			//
			//	Static Member Functions
			//
			public:

				/**
				Default null \c step function called if Lua does not provide a specialisation.
				@param state The lua state object being called.
				@param delta_time The time passed since the last update.
				@return Always returns the shared_ptr to \c state.
				\author Sean Tromans
				*/
				static state_ptr default_step( game_state * /*state*/, time const & /*delta_time*/ )
				{
					throw sun::lua::not_implemented_exception( "sun.game_state.step" );
				}

				/**
				Default null \c pre_draw function called if Lua does not provide a specialisation.
				\author Sean Tromans
				*/
				static void default_pre_draw( game_state * /*state*/, float /*step_fraction*/, rainbow::viewport_stack & /*queue*/ )
				{
					throw sun::lua::not_implemented_exception( "sun.game_state.pre_draw" );
				}
		};
#endif

	};

	/**
	Exposes the \c game_state class to the lua state.
	@param L The lua_State being initialised.
	\author Sean Tromans
	*/
	void game_state::lua_interface( lua_State * L )
	{
#if !defined(SUN_DISABLE_LUA)
		luabind::module( L, "sun" )
		[
			luabind::class_< game_state, detail::game_state_wrapper, state_ptr >( "game_state" )
				.def( luabind::constructor<>( ) )
				.def( "step",		&game_state::step,		&detail::game_state_wrapper::default_step )
				.def( "pre_draw",	&game_state::pre_draw,	&detail::game_state_wrapper::default_pre_draw )
		];
#else
		NMN_UNUSED( L );
#endif
	}

};
